﻿using Common.AspNetCore;
using Common.Enums.FCP;
using Common.Infrastructure;
using FCP.Api.Models;
using FCP.Api.Repository;
using FCP.Api.Utils;
using FCP.Data.Entity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace FCP.Api.Service
{
    public class FCPConfigService : CommonService
    {
        private readonly FCPRepository fcpRepository;

        public FCPConfigService(IServiceProvider provider, FCPRepository fcp) : base(provider)
        {
            this.fcpRepository = fcp;
        }


        private async Task<SearchConfigModel> GetSearchConfigModelAsync(t_form form, string lang)
        {
            var search = await this.fcpRepository.CommonRepository.GetEntityAsync<t_search>(null, t => t.fcp_form_id == form.id);
            if (search == null) return null;
            List<t_search> searchs = new List<t_search>();
            searchs.Add(search);
            await EntityToWebModelUtls.GetSearchLabelsAsync(searchs, lang, this.fcpRepository.CommonRepository); ;
            var searchConfig = new SearchConfigModel()
            {
                Code = search.code,
                Search = search
            };

            if (searchConfig != null)
            {
                Expression<Func<t_search_field, bool>> expression =
                    t => t.fcp_form_id == form.id && t.search_id == search.id && t.is_visible;
                //if (!string.IsNullOrEmpty(code))
                //    expression = expression.And(t => t.code == code);
                var searchFields = await this.fcpRepository.CommonRepository.GetEntitiesAsync<t_search_field>(expression);
                var searchFieldIds = searchFields.Select(t => t.id).ToList();
                await EntityToWebModelUtls.GetSearchFieldLabelsAsync(searchFields.ToList(), LibMessageUtils.GetLang(this.Provider), this.fcpRepository.CommonRepository);
                var searchFieldFilters = await this.fcpRepository.CommonRepository.GetEntitiesAsync<t_search_field_filter_field>(t => searchFieldIds.Contains(t.search_field_id));
                searchFields.OrderBy(t => t.num).ForEach(t =>
                {
                    var searchField = new SearchFieldConfigModel() { Field = t };
                    searchConfig.Fields.Add(searchField);

                    searchFieldFilters.Where(t1 => t1.search_field_id == t.id).ForEach(t1 =>
                    {
                        searchField.FilterFields.Add(new SearchFieldFilterConfigModel() { FilterField = t1 });
                    });
                });
            }
            return searchConfig;
        }



        public async Task<FCPSearchConfigModel> GetSearchConfigAsync(ApiParam apiParam)
        {
            var lang = apiParam.Lang;
            if (string.IsNullOrEmpty(lang))
            {
                lang = LibMessageUtils.GetLang(this.Provider);
            }

            apiParam.OrgType = FilterOrgTypeEnum.OnlyOrg;
            var formCode = apiParam.Keyword;
            var access = this.fcpRepository.CommonRepository;
            var form = await access.GetEntityAsync<t_form>(apiParam, t => t.code == formCode);
            if (form == null) return null;
            var fcpConfig = new FCPSearchConfigModel();
            fcpConfig.Form = form;
            fcpConfig.SearchConfig = await GetSearchConfigModelAsync(form, lang);
            return fcpConfig;

        }


        public async Task<FCPTableConfigModel> GetTableConfigAsync(ApiParam apiParam)
        {
            var lang = apiParam.Lang;
            if (string.IsNullOrEmpty(lang))
            {
                lang = LibMessageUtils.GetLang(this.Provider);
            }

            apiParam.OrgType = FilterOrgTypeEnum.OnlyOrg;
            var access = this.fcpRepository.CommonRepository;
            var form = await access.GetEntityAsync<t_form>(apiParam, t => t.code == apiParam.Keyword);
            if (form == null) return null;
            var fcpConfig = new FCPTableConfigModel();
            fcpConfig.Form = form;
            fcpConfig.SearchConfig = await GetSearchConfigModelAsync(form, lang);
            var tables = await access.GetEntitiesAsync<t_table>(t => t.fcp_form_id == form.id && t.is_visible);
            if (tables.Any())
            {
                var tableIds = tables.Select(t => t.id).ToList();
                var tableFilterFields = await access.GetEntitiesAsync<t_table_filter_field>(t => tableIds.Contains(t.table_id));
                var tablePanels = await access.GetEntitiesAsync<t_table_panel>(t => tableIds.Contains(t.table_id) && t.is_visible);
                var tableBtns = await access.GetEntitiesAsync<t_table_btn>(t => tableIds.Contains(t.table_id) && t.is_visible);
                var tableFields = await access.GetEntitiesAsync<t_table_field>(t => tableIds.Contains(t.table_id));
                var tableFieldIds = tableFields.Select(t => t.id).ToList();
                var tableFieldFilters = await access.GetEntitiesAsync<t_table_field_filter_field>(t =>
                        tableIds.Contains(t.table_id) && tableFieldIds.Contains(t.table_field_id));
                await EntityToWebModelUtls.GetTableLabelsAsync(tables.ToList(), lang, this.fcpRepository.CommonRepository); ;
                await EntityToWebModelUtls.GetTablePanelLabelsAsync(tablePanels.ToList(), lang, this.fcpRepository.CommonRepository); ;
                await EntityToWebModelUtls.GetTableBtnLabelsAsync(tableBtns.ToList(), lang, this.fcpRepository.CommonRepository); ;
                await EntityToWebModelUtls.GetTableFieldLabelsAsync(tableFields.ToList(), lang, this.fcpRepository.CommonRepository); ;
                DoGetTableConfig(tables, form, null, null, fcpConfig, tableFilterFields,
                        tablePanels, tableBtns, tableFields, tableFieldFilters);
            }
            return fcpConfig;

        }

        private void DoGetTableConfig(List<t_table> tables, t_form form, string parentId,
            TableConfigModel parentTableConfigMode, FCPTableConfigModel fcpConfig,
            List<t_table_filter_field> tableFilterFields,
            List<t_table_panel> tablePanels, List<t_table_btn> tableBtns,
                List<t_table_field> tableFields,
                List<t_table_field_filter_field> tableFieldFilters)
        {

            var tempTables = tables.Where(t => t.parent_id == parentId).OrderBy(t=>t.num).ToList();
            if (!tempTables.Any()) return;
            foreach (var table in tempTables)
            {
                var tableConfigModel = new TableConfigModel();
                tableConfigModel.Code = table.code;
                tableConfigModel.Table = table;
                //  tableConfigModel.Form = form;
                if (string.IsNullOrEmpty(parentId))
                    tableConfigModel.IsTop = true;
                if (parentTableConfigMode != null)
                {
                    parentTableConfigMode.HasChildren = true;
                    parentTableConfigMode.ChildrenCodes.Add(tableConfigModel.Code);
                }
                tableFilterFields.Where(t => t.table_id == table.id).ForEach(t =>
                {
                    var temp = new TableFilterFieldConfigModel() { FilterField = t };
                    tableConfigModel.FilterFields.Add(temp);
                });
                tablePanels.Where(t => t.table_id == table.id).OrderBy(t => t.num).ForEach(t =>
                {
                    var temp = new TablePanelConfigModel() { Panel = t };
                    tableConfigModel.Panels.Add(temp);
                });
                tableBtns.Where(t => t.table_id == table.id && (t.btn_type == (int)FCPBtnTypeEnum.刷新 ||
                t.btn_type == (int)FCPBtnTypeEnum.导入 ||
                t.btn_type == (int)FCPBtnTypeEnum.导出 ||
                t.btn_type == (int)FCPBtnTypeEnum.批量删除 ||
                t.btn_type == (int)FCPBtnTypeEnum.新增 ||
                t.btn_type == (int)FCPBtnTypeEnum.批量自定义 ||
                t.btn_type == (int)FCPBtnTypeEnum.批量API)).OrderBy(t => t.num).ForEach(t =>
                {
                    var temp = new TableBtnConfigModel() { Btn = t };
                    tableConfigModel.Btns.Add(temp);
                });
                tableBtns.Where(t => t.table_id == table.id && (t.btn_type == (int)FCPBtnTypeEnum.API ||
                t.btn_type == (int)FCPBtnTypeEnum.删除 ||
                t.btn_type == (int)FCPBtnTypeEnum.复制新增 ||
                t.btn_type == (int)FCPBtnTypeEnum.查看 ||
                t.btn_type == (int)FCPBtnTypeEnum.编辑 ||
                t.btn_type == (int)FCPBtnTypeEnum.自定义)).OrderBy(t => t.num).ForEach(t =>
                {
                    var temp = new TableBtnConfigModel() { Btn = t };
                    tableConfigModel.RowBtns.Add(temp);
                });
                tableFields.Where(t => t.table_id == table.id).OrderBy(t => t.num).ForEach(t =>
                {
                    var temp = new TableFieldConfigModel() { Field = t };
                    tableFieldFilters.Where(t1 => t1.table_id == table.id && t1.table_field_id == t.id).ForEach(t1 =>
                    {
                        var temp1 = new TableFieldFilterFieldConfigModel() { FilterField = t1 };
                        temp.FilterFields.Add(temp1);
                    });
                    tableConfigModel.Fields.Add(temp);
                });
                fcpConfig.Tables.Add(tableConfigModel);

                DoGetTableConfig(tables, form, table.id, tableConfigModel, fcpConfig, tableFilterFields,
                    tablePanels, tableBtns, tableFields, tableFieldFilters);
            }

        }



        public async Task<FCPEditConfigModel> GetEditConfigAsync(ApiParam apiParam)
        {
            var lang = apiParam.Lang;
            if (string.IsNullOrEmpty(lang))
            {
                lang = LibMessageUtils.GetLang(this.Provider);
            }

            var access = this.fcpRepository.CommonRepository;
            var form = await access.GetEntityAsync<t_form>(apiParam, t => t.code == apiParam.Keyword);
            if (form == null) return null;
            var fcpConfig = new FCPEditConfigModel();
            fcpConfig.Form = form;
            var tables = await access.GetEntitiesAsync<t_edit>(t => t.fcp_form_id == form.id && t.is_visible);
            if (tables.Any())
            {
                var tableIds = tables.Select(t => t.id).ToList();
                var tablePanels = await access.GetEntitiesAsync<t_edit_panel>(t => tableIds.Contains(t.edit_id) && t.is_visible);
                var tableBtns = await access.GetEntitiesAsync<t_edit_btn>(t => tableIds.Contains(t.edit_id) && t.is_visible);
                var tableFields = await access.GetEntitiesAsync<t_edit_field>(t => tableIds.Contains(t.edit_id));
                var tableFieldIds = tableFields.Select(t => t.id).ToList();
                var tableFieldFilters = await access.GetEntitiesAsync<t_edit_field_filter_field>(t =>
                        tableIds.Contains(t.edit_id) && tableFieldIds.Contains(t.edit_field_id));
                var editFieldMaps = await access.GetEntitiesAsync<t_edit_field_map>(t =>
                        tableFieldIds.Contains(t.edit_field_id));
                var editFieldMapIds = editFieldMaps.Select(t => t.id).ToList();
                List<t_edit_field_map_detail> editFieldMapDetails = null;
                if (editFieldMapIds.Any())
                    editFieldMapDetails = await access.GetEntitiesAsync<t_edit_field_map_detail>(t =>
                         editFieldMapIds.Contains(t.edit_field_map_id));

                await EntityToWebModelUtls.GetEditLabelsAsync(tables.ToList(), lang, this.fcpRepository.CommonRepository); ;
                await EntityToWebModelUtls.GetEditPanelLabelsAsync(tablePanels.ToList(), lang, this.fcpRepository.CommonRepository); ;
                await EntityToWebModelUtls.GetEditBtnLabelsAsync(tableBtns.ToList(), lang, this.fcpRepository.CommonRepository); ;
                await EntityToWebModelUtls.GetEditFieldLabelsAsync(tableFields.ToList(), lang, this.fcpRepository.CommonRepository); ;

                DoGetEditConfig(tables, form, null, null, fcpConfig,
                        tablePanels, tableBtns, tableFields, editFieldMaps, editFieldMapDetails,
                            tableFieldFilters);
            }
            return fcpConfig;

        }


        private void DoGetEditConfig(List<t_edit> tables, t_form form, string parentId,
          EditConfigModel parentTableConfigMode, FCPEditConfigModel fcpConfig,
          List<t_edit_panel> tablePanels, List<t_edit_btn> tableBtns,
              List<t_edit_field> tableFields, List<t_edit_field_map> editFieldMaps,
              List<t_edit_field_map_detail> editFieldMapDetails,
              List<t_edit_field_filter_field> tableFieldFilters)
        {

            var tempTables = tables.Where(t => t.parent_id == parentId).OrderBy(t => t.num).ToList();
            if (!tempTables.Any()) return;
            foreach (var table in tempTables)
            {
                var tableConfigModel = new EditConfigModel();
                tableConfigModel.Code = table.code;
                tableConfigModel.Edit = table;
                // tableConfigModel.Form = form;
                if (string.IsNullOrEmpty(parentId))
                    tableConfigModel.IsTop = true;
                if (parentTableConfigMode != null)
                    parentTableConfigMode.HasChildren = true;
                tablePanels.Where(t => t.edit_id == table.id).OrderBy(t => t.num).ForEach(t =>
                {
                    var temp = new EditPanelConfigModel() { Panel = t };
                    tableConfigModel.Panels.Add(temp);
                });
                tableBtns.Where(t => t.edit_id == table.id && (t.btn_type == (int)FCPBtnTypeEnum.保存 ||
                t.btn_type == (int)FCPBtnTypeEnum.批量删除 || t.btn_type == (int)FCPBtnTypeEnum.批量自定义 ||
                t.btn_type == (int)FCPBtnTypeEnum.新增)).OrderBy(t => t.num).ForEach(t =>
                {
                    var temp = new EditBtnConfigModel() { Btn = t };
                    tableConfigModel.Btns.Add(temp);
                });
                tableBtns.Where(t => t.edit_id == table.id && (
                t.btn_type == (int)FCPBtnTypeEnum.删除 || t.btn_type == (int)FCPBtnTypeEnum.自定义 ||
                t.btn_type == (int)FCPBtnTypeEnum.编辑)).OrderBy(t => t.num).ForEach(t =>
                {
                    var temp = new EditBtnConfigModel() { Btn = t };
                    tableConfigModel.RowBtns.Add(temp);
                });
                tableFields.Where(t => t.edit_id == table.id).OrderBy(t => t.num).ForEach(t =>
                {
                    var temp = new EditFieldConfigModel() { Field = t };
                    tableFieldFilters.Where(t1 => t1.edit_id == table.id && t1.edit_field_id == t.id).ForEach(t1 =>
                    {
                        var temp1 = new EditFieldFilterFieldConfigModel() { FilterField = t1 };
                        temp.FilterFields.Add(temp1);
                    });
                    tableConfigModel.Fields.Add(temp);

                    editFieldMaps.Where(t1 => t1.edit_field_id == t.id).ForEach(t1 =>
                    {
                        var temp1 = new EditFieldMapConfigModel() { Map = t1 };
                        temp.Maps.Add(temp1);
                        editFieldMapDetails.Where(t2 => t2.edit_field_map_id == t1.id).ForEach(t2 =>
                        {
                            var temp2 = new EditFieldMapDetailConfigModel() { MapDetail = t2 };
                            temp1.Details.Add(temp2);
                        });
                    });
                });
                // tableConfigModel.ParentEdit = parentTableConfigMode;
                if (parentTableConfigMode != null)
                {
                    if (parentTableConfigMode.IsTop)
                    {
                        tableConfigModel.IsSubTop = true;
                        fcpConfig.SubEdits.Add(tableConfigModel);
                    }
                    else
                        parentTableConfigMode.SubEdits.Add(tableConfigModel);
                }
                else
                    fcpConfig.Edit = tableConfigModel;

                if (parentTableConfigMode != null)
                    tableConfigModel.NavFields = parentTableConfigMode.NavFields;
                if (!string.IsNullOrEmpty(tableConfigModel.NavFields))
                    tableConfigModel.NavFields += ".";
                tableConfigModel.NavFields += table.parent_nav_field_name;

                DoGetEditConfig(tables, form, table.id, tableConfigModel, fcpConfig,
                    tablePanels, tableBtns, tableFields, editFieldMaps, editFieldMapDetails,
                        tableFieldFilters);
            }

        }



        public async Task<FCPTreeConfigModel> GetTreeConfigAsync(ApiParam apiParam)
        {
            var lang = apiParam.Lang;
            if (string.IsNullOrEmpty(lang))
            {
                lang = LibMessageUtils.GetLang(this.Provider);
            }

            var access = this.fcpRepository.CommonRepository;
            var form = await access.GetEntityAsync<t_form>(apiParam, t => t.code == apiParam.Keyword);
            if (form == null) return null;
            var fcpConfig = new FCPTreeConfigModel();
            fcpConfig.Form = form;
            var table = await access.GetEntityAsync<t_tree>(null, t => t.fcp_form_id == form.id);
            if (table != null)
            {
                var tableBtns = await access.GetEntitiesAsync<t_tree_btn>(t => t.tree_id == table.id);
                var tableFields = await access.GetEntitiesAsync<t_tree_field>(t => t.tree_id == table.id);
                List<t_tree> tables = new List<t_tree>();
                tables.Add(table);
                await EntityToWebModelUtls.GetTreeLabelsAsync(tables.ToList(), lang, this.fcpRepository.CommonRepository); ;
                await EntityToWebModelUtls.GetTreeBtnLabelsAsync(tableBtns.ToList(), lang, this.fcpRepository.CommonRepository); ;
                await EntityToWebModelUtls.GetTreeFieldLabelsAsync(tableFields.ToList(), lang, this.fcpRepository.CommonRepository); ;

                TreeConfigModel treeConfig = new TreeConfigModel();
                fcpConfig.Tree = treeConfig;
                treeConfig.Tree = table;

                tableBtns.Where(t => t.tree_id == table.id && t.btn_func_type == 0).OrderBy(t => t.num).ForEach(t =>
                {
                    var temp = new TreeBtnConfigModel() { Btn = t };
                    treeConfig.Btns.Add(temp);
                });
                tableFields.Where(t => t.tree_id == table.id).OrderBy(t => t.num).ForEach(t =>
                {
                    var temp = new TreeFieldConfigModel() { Field = t };
                    treeConfig.Fields.Add(temp);

                });
            }
            return fcpConfig;
        }

    }
}
